package org.localdb.localdb.backend.tm;

import org.localdb.localdb.backend.utils.Panic;
import org.localdb.localdb.common.Error;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public interface TransactionManager {
    long begin();   //开启事务
    void commit(long xid);  //提交事务
    void abort(long xid);   //撤销或回滚事务
    boolean isActive(long xid);    //查询一个事务的状态是否活跃
    boolean isCommitted(long xid);  //查询一个事务的状态是否已经提交
    boolean isAborted(long xid);    //查询一个事务的状态是否撤销或者回滚
    void close();   //关闭事务

    static TransactionManagerImpl creat(String path){
        File f = new File(path+TransactionManagerImpl.XID_SUFFIX);
        try{
            if (!f.createNewFile()){
                Panic.panic(Error.FileExistsException);
            }
        }catch (Exception e){
            Panic.panic(e);
        }
        if (!f.canRead() || !f.canWrite()){
            Panic.panic(Error.FileCannotRWException);
        }

        FileChannel fc = null;
        RandomAccessFile raf = null;

        try{
            raf = new RandomAccessFile(f,"rw");
            fc = raf.getChannel();
        }catch (FileNotFoundException e){
            Panic.panic(Error.FileCannotRWException);
        }

        ByteBuffer buf = ByteBuffer.wrap(new byte[TransactionManagerImpl.LEN_XID_HEADER_LENGTH]);

        try{
            fc.position(0);
            fc.write(buf);
        }catch (IOException e){
            Panic.panic(e);
        }
        return new TransactionManagerImpl(raf, fc);
    }

    static TransactionManagerImpl open(String path){
        File f = new File(path+TransactionManagerImpl.XID_SUFFIX);

        if (!f.exists()){
            Panic.panic(Error.FileNotExistsException);
        }
        if (!f.canRead() ||!f.canWrite()){
            Panic.panic(Error.FileCannotRWException);
        }

        FileChannel fc = null;
        RandomAccessFile raf = null;

        try{
            raf = new RandomAccessFile(f,"rw");
            fc = raf.getChannel();
        }catch (FileNotFoundException e){
            Panic.panic(e);
        }
        return new TransactionManagerImpl(raf,fc);
    }
}
